/*
 * Copyright 2004-2005 asoft
 * 本软件及其所有拷贝的名称，与光盘上或本软件中注明的公司同在。
 * 本软件及文档享有版权，并受国家版权法及国际协约条款的保护。
 * 您不可以从本软件中去掉其版权声明；并保证为本软件的拷贝（本部或部分）* 复制版权声明。
 * 您同意制止以任何形式非法拷贝本软件及文档。
 * 版权信息参见：
 *      http://www.asoft.cn/licenses
 */

package com.asoft.common.base.dao;

import java.io.Serializable;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Expression;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.asoft.common.base.model.BaseObject;

/**
 * This class serves as the Base class for all other DAOs - namely to hold
 * common methods that they might all use. Can be used for standard CRUD
 * operations.</p>
 *
 * <p><a href="BaseDAOHibernate.java.html"><i>View Source</i></a></p>
 *
 * @author amon
 */
public abstract class BaseDAOHibernate extends HibernateDaoSupport
                                       implements DAO
{
        static Logger logger = Logger.getLogger(BaseDAOHibernate .class);

        /** 实体类 */
        private Class entityClass;

        public Class getEntityClass()
        {
                return this.entityClass;
        }

        public void setEntity(BaseObject entity)
        {
                this.entityClass = entity.getClass();
        }

        /**
         * 向数据库插入一条记录(BaseObject)
         *
         * @param: Object model BaseObject的子类型，为unsave
         *
         * return saved类型的 BaseObject，其id已经被附值
         */
        public Object save(Object o)
        {
                logger.debug("开始save()");
                this.getHibernateTemplate().save(o);
                return o;
        }
        
        /**
         * 新增实体s
         * reutnr 修改后的实体s
         */
        public List saveAll(List objs)
        {
                for (int i = 0; i < objs.size(); i++)
                {
                        this.save(objs.get(i));
                }
                return objs;
        }

        /**
         * 更新数据入一条记录(BaseObject)
         *
         * @param: Object model BaseObject的子类型
         *
         * return saved类型的 BaseObject
         */
        public Object update(Object o)
        {
                logger.debug("update()");
                return this.getHibernateTemplate().merge(o);
        }

        public List updateAll(List o)
        {
                logger.debug("updateAll()");
                for (int i = 0; i < o.size(); i++)
                {
                        this.update(o.get(i));
                }
                return o;
        }

        /**
         * 批量插入or更新记录(BaseObject)
         *
         * @param: Object model BaseObject的子类型
         *
         * return saved类型的 BaseObject
         */
        public List saveOrUpdateAll(List objs)
        {
                logger.debug("开始saveOrUpdateAll()");
                this.getHibernateTemplate().saveOrUpdateAll(objs);
                return objs;
        }

        /**
         * 删除一条记录(BaseObject)
         *
         * @param: Object model BaseObject的子类型
         */
        public void remove(Object obj)
        {
                this.getHibernateTemplate().delete(obj);
        }

        /**
         * 批量删除多条记录(BaseObject)
         *
         * @param: Object model BaseObject集合
         */
        public void removeAll(List objs)
        {
                this.getHibernateTemplate().deleteAll(objs);
        }

        /**
         * 查询byId
         *
         * @ param: id
         * @ return 查询结果
         */
        public Object get(Serializable id)
        {
                Object entity = this.getHibernateTemplate().get(entityClass, id);
                if (entity == null)
                {
                        logger.error("id为'" + id + "' 的" + entityClass + "对应的model不存在");
                }
                return entity;
        }
        
        /**
         * 查询byCode
         *
         * @ param: Code
         * @ return 查询结果
         */
        public Object getByCode(String code)
        {
                return this.getByCode(code,null);
        }
        
        /**
         * 可加条件的查询byCode 
         * 
         * @param code
         * @param hibernateExpressions 条件集合
         * @return
         */
        protected Object getByCode(final String code,
                                   final List hibernateExpressions)
        {
                return this.getByBusinessKey("code",code,hibernateExpressions);
        }
        
        /**
         * 根据业务主键查询实体
         * 
         * @param businessKeyName 业务主键对应的属性名(4 hql)
         * @param businessKeyValue 业务主键的值
         * @param hibernateExpressions 条件集合
         * @return BaseObject
         */
        protected Object getByBusinessKey(final String businessKeyName,
                                          final Serializable businessKeyValue,
                                          final List hibernateExpressions)
        {
                final Class ec = this.entityClass;
                return (Object) this.getHibernateTemplate().execute(new HibernateCallback() 
                {
                        public Object doInHibernate(Session session) throws HibernateException 
                        {
                                Criteria cir = session.createCriteria(ec).add(Expression.eq(businessKeyName, businessKeyValue));
                                if(hibernateExpressions != null)
                                {
                                        for(int i = 0; i < hibernateExpressions.size(); i ++)
                                        {
                                                cir.add((Criterion)hibernateExpressions.get(i));
                                        }
                                }
                                List boes = cir.list();
                                if(boes.size() > 1)
                                {
                                        throw new HibernateException(businessKeyName + "为'" + businessKeyValue + "'的实体有" + boes.size() + "个");
                                }
                                if(boes.size() == 0)
                                {
                                        return null;
                                }
                                return boes.get(0);
                        }
                });
        }

        /**
         * 清楚session缓存
         */
        public void evict(Object obj)
        {
                this.getHibernateTemplate().evict(obj);
        }

        /**
         * 作废然后新增
         *    用于维护记录的所有版本而使用的
         */
        public Object blankOutThenSave(Object obj)
        {
                throw new RuntimeException("blankOutThenSave()方法未实现");
        }
        
        /**
         * 清空所有数据
         * @warn:　用于单元测试用,危险的api
         */
        public void clearAll()
        {
                final Class ec = this.entityClass;
                List all = (List)this.getHibernateTemplate().execute(new HibernateCallback() 
                {
                        public Object doInHibernate(Session session) throws HibernateException 
                        {
                                Criteria cir = session.createCriteria(ec);
                                return cir.list();
                        }
                });
                this.removeAll(all);
        }
        
        /** Iterator 2 List */
        public List iterator2List(Iterator iterator)
        {
                List list = new Vector(100);
                while(iterator.hasNext())
                {
                        list.add(iterator.next());
                }
                return list;
        }
}
